﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace XChip_Common
{

    public enum SensorOptionType
    {
        Enum8Addr8Data = 0,
        Enum16Addr8Data = 1,
        Enum16Addr16Data = 2,
        Enum32Addr8Data = 3,
        Enum32Addr16Data = 4,
        Enum32Addr32Data = 5,

    }

    public enum WaitTypeEnum
    {
        SOON =0,
        EOF = 1,
        SOF =2,
        OTHER =3,
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DeviceInfo {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
        public string DevicePath;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
        public string DeviceName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
        public string PID;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
        public string VID;

        //public String deviceName
        //{
        //    get {
        //        StringBuilder sb = new StringBuilder();
        //        foreach (var item in DeviceName)
        //        {
        //            if (item == '\0')  continue;
        //            sb.Append(item);
        //        }
        //        return sb.ToString(); }
        //}

    }

   public class XChipUSB
    {
        public delegate void CallBackType(int hr, int process);
        public delegate void WriteFileCallback(bool success, int status);

        [StructLayout(LayoutKind.Sequential)]
        public struct CallBackInfo
        {
            public int progress; // 进度：0-100  
            public int result;   // 状态： >=0为正常，<0为失败  
        }
        // 定义与C++回调函数匹配的委托
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void WriteFileCallBackType([MarshalAs(UnmanagedType.I1)] bool success, int progress);
        /// <summary>
        /// 设备列表信息
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbGetDevice", CallingConvention = CallingConvention.Cdecl)]
        [Obsolete("2024.3.15 前可以使用当前方法更新为UsbGetAllDeviceInfo 请调用新的方法")]
        public static extern IntPtr UsbGetDevice86( int DeviceList);
        /// <summary>
        /// 设备列表信息
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbGetDevice", CallingConvention = CallingConvention.Cdecl)]
        [Obsolete("2024.3.15 前可以使用当前方法更新为UsbGetAllDeviceInfo 请调用新的方法")]
        public static extern IntPtr UsbGetDevice64( int DeviceList);


        /// <summary>
        /// 获取所有设备的信息，调用方负责保证指针地址有效性；
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbGetAllDeviceInfo_MultiplexInterface", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbGetAllDeviceInfo86();
        /// <summary>
        /// 获取所有设备的信息，调用方负责保证指针地址有效性；
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbGetAllDeviceInfo_MultiplexInterface", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbGetAllDeviceInfo64();


        /// <summary>
        /// 初始化设备时请务必调用此接口，调用此接口后，才能进行其他的设备操作，调用一次即可
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbIniDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbIniDevice86();
        /// <summary>
        /// 初始化设备时请务必调用此接口，调用此接口后，才能进行其他的设备操作，调用一次即可
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbIniDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbIniDevice64();


        /// <summary>
        /// 更新设备时请调用此接口，如果设备有变化，需再次调用此函数才能刷新设备信息；返回true代表成功，false代表失败
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbUpdateDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbUpdateDevice86();
        /// <summary>
        /// 更新设备时请调用此接口，如果设备有变化，需再次调用此函数才能刷新设备信息；返回true代表成功，false代表失败
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbUpdateDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr UsbUpdateDevice64();

        /// <summary>
        /// 从定义的设备选择列表选择设备时
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbSelectDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbSelectDevice86(int DeviceList);
        /// <summary>
        /// 从定义的设备选择列表选择设备时
        /// </summary>
        /// <param name="DeviceList"></param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbSelectDevice", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbSelectDevice64(int DeviceList);

        //[DllImport("X86/XChipUSB.dll", EntryPoint = "UsbOpenDevice", CallingConvention = CallingConvention.Cdecl)]
        //public extern static bool UsbOpenDevice86( DeviceInfo Data);

        //[DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbOpenDevice", CallingConvention = CallingConvention.Cdecl)]
        //public extern static bool UsbOpenDevice64( DeviceInfo Data);
        /// <summary>
        /// 获取设备数量，注意如果设备数量有变化，需要调用UsbUpdateDevice后才会刷新
        /// </summary>
        /// <param name="index">传入的设备序号</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbGetDeviceNum", CallingConvention = CallingConvention.Cdecl)]
        public static extern int UsbGetDeviceNum86();
        /// <summary>
        /// 获取设备数量，注意如果设备数量有变化，需要调用UsbUpdateDevice后才会刷新
        /// </summary>
        /// <param name="index">传入的设备序号</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbGetDeviceNum", CallingConvention = CallingConvention.Cdecl)]
        public static extern int UsbGetDeviceNum64();


        /// <summary>
        /// FlashRead 86读
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbFlashRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashRead86(uint Addr, ref uint pValue);
        /// <summary>
        /// FlashRead 64读
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbFlashRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashRead64(uint Addr,ref uint pValue);

        /// <summary>
        /// FlashWrite 86写
        /// </summary>
        /// <param name="Addr"></param>
        /// <param name="pValue"></param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbFlashWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashWrite86(uint Addr,  uint pValue);
        /// <summary>
        /// FlashWrite 64写
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbFlashWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashWrite64(uint Addr,  uint pValue);

        /// <summary>
        /// RegisterRead 86读
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Isbit32">true为32位寄存器读模式，false为8位寄存器读模式</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbRegisterRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterRead86(uint Addr, ref uint pValue, bool Isbit32);
        /// <summary>
        /// RegisterRead 64读
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Isbit32">true为32位寄存器读模式，false为8位寄存器读模式</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbRegisterRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterRead64(uint Addr,ref uint pValue, bool Isbit32);

        /// <summary>
        /// RegisterWrite 86写
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Isbit32">true为32位寄存器写模式，false为8位寄存器写模式</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbRegisterWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterWrite86(uint Addr, uint pValue, bool Isbit32);
        /// <summary>
        /// RegisterWrite 64写
        /// </summary>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Isbit32">true为32位寄存器写模式，false为8位寄存器写模式</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbRegisterWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterWrite64(uint Addr, uint pValue, bool Isbit32);


        /// <summary>
        /// I2cRead 86读
        /// </summary>
        /// <param name="ID">i2c的ID</param>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Type">地址的数据格式</param>
        /// <param name="WaitType">读写时间点</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbI2cRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2cRead86(uint ID, uint Addr, ref uint pValue, int Type, int WaitType);
        /// <summary>
        /// I2cRead 64读
        /// </summary>
        /// <param name="ID">i2c的ID</param>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Type">地址的数据格式</param>
        /// <param name="WaitType">读写时间点</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbI2cRead", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2cRead64(uint ID, uint Addr, ref uint pValue, int Type, int WaitType);

        /// <summary>
        ///  I2cWrite 86写
        /// </summary>
        /// <param name="ID">i2c的ID</param>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Type">地址的数据格式</param>
        /// <param name="WaitType">读写时间点</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbI2cWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2cWrite86(uint ID, uint Addr, uint pValue, int Type, int WaitType);

        /// <summary>
        /// I2cWrite 64写
        /// </summary>
        /// <param name="ID">i2c的ID</param>
        /// <param name="Addr">地址</param>
        /// <param name="pValue">值</param>
        /// <param name="Type">地址的数据格式</param>
        /// <param name="WaitType">读写时间点</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbI2cWrite", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2cWrite64(uint ID, uint Addr, uint pValue, int Type, int WaitType);

        /// <summary>
        /// FlashErase 86
        /// </summary>
        /// <param name="Addr">擦除的地址</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbFlashErase", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashErase86(uint Addr);
        /// <summary>
        /// FlashErase 64
        /// </summary>
        /// <param name="Addr">擦除的地址</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbFlashErase", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashErase64(uint Addr);
        /// <summary>
        /// FlashWriteFile 86
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbFlashWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashWriteFile86(string FileName, uint Addr, WriteFileCallBackType callBackFun);
        /// <summary>
        /// FlashWriteFile 64
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbFlashWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashWriteFile64(string FileName, uint Addr , WriteFileCallBackType callBackFun);

        /// <summary>
        /// FlashQuickReadFile 86
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <param name="csBeginAddr">起始地址</param>
        /// <param name="csEndAddr">结束地址</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbFlashQuickReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashQuickReadFile86(string FileName, uint csBeginAddr, uint csEndAddr);
        /// <summary>
        ///  FlashQuickReadFile 64
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <param name="csBeginAddr">起始地址</param>
        /// <param name="csEndAddr">结束地址</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbFlashQuickReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbFlashQuickReadFile64(string FileName, uint csBeginAddr, uint csEndAddr);

        /// <summary>
        /// RegisterReadFile 86
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <param name="csBeginAddr">起始地址</param>
        /// <param name="csEndAddr">结束地址</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbRegisterReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterReadFile86(string FileName, uint csBeginAddr, uint csEndAddr);
        /// <summary>
        /// RegisterReadFile 64
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <param name="csBeginAddr">起始地址</param>
        /// <param name="csEndAddr">结束地址</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbRegisterReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterReadFile64(string FileName, uint csBeginAddr, uint csEndAddr);

        /// <summary>
        /// UsbRegisterWriteFile 86
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbRegisterWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterWriteFile86(string FileName);
        /// <summary>
        /// UsbRegisterWriteFile 64
        /// </summary>
        /// <param name="FileName">文件的绝对路径</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbRegisterWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbRegisterWriteFile64(string FileName);
        /// <summary>
        /// I2CReadFile 86
        /// </summary>
        /// <param name="l_lStaeradd">起始地址</param>
        /// <param name="l_lSendadd">结束地址</param>
        /// <param name="l_csPath">文件的绝对路径</param>
        /// <param name="l_lSIDAdd">ID值</param>
        /// <param name="sensor">数据格式</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbI2CReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2CReadFile86(uint l_lStaeradd, uint l_lSendadd, string l_csPath, int l_lSIDAdd, int sensor);
        /// <summary>
        ///  I2CReadFile 64
        /// </summary>
        /// <param name="l_lStaeradd">起始地址</param>
        /// <param name="l_lSendadd">结束地址</param>
        /// <param name="l_csPath">文件的绝对路径</param>
        /// <param name="l_lSIDAdd">ID值</param>
        /// <param name="sensor">数据格式</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbI2CReadFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2CReadFile64(uint l_lStaeradd, uint l_lSendadd, string l_csPath, int l_lSIDAdd, int sensor);
        /// <summary>
        /// I2CWriteFile 86
        /// </summary>
        /// <param name="csFile">文件的绝对路径</param>
        /// <param name="WaitType">写入时间点</param>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbI2CWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2CWriteFile86(string csFile, int WaitType);
        /// <summary>
        /// I2CWriteFile 64
        /// </summary>
        /// <param name="csFile">文件的绝对路径</param>
        /// <param name="WaitType">写入时间点</param>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbI2CWriteFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbI2CWriteFile64(string csFile, int WaitType);

        /// <summary>
        /// 关闭与设备的连接并释放资源 86
        /// </summary>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "UsbDestroyUSB", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbDestroyUSB86();
        /// <summary>
        /// 关闭与设备的连接并释放资源 64
        /// </summary>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "UsbDestroyUSB", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool UsbDestroyUSB64();


        /// <summary>
        /// 文件读写接口调用之后，调用此接口获取进度与状态
        /// </summary>
        /// <returns></returns>
        [DllImport("X86/XChipUSB.dll", EntryPoint = "GetProgressInfo", CallingConvention = CallingConvention.Cdecl)]
        public static extern CallBackInfo GetProgressInfo86();
        /// <summary>
        /// 文件读写接口调用之后，调用此接口获取进度与状态
        /// </summary>
        /// <returns></returns>
        [DllImport("X64/XChipUSB_x64.dll", EntryPoint = "GetProgressInfo", CallingConvention = CallingConvention.Cdecl)]
        public static extern CallBackInfo GetProgressInfo64();

        public static async Task<bool> WriteFileAsync(string fileName, uint startAddr)
        {
            TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
            WriteFileCallBackType callback = (success, status) =>
            {
                // 检查是否完成或失败  
                if (success && status == 100 || !success)
                {
                    tcs.SetResult(success);
                }
            };
            bool started = false;
            // 启动异步文件写入  
            if (IntPtr.Size == 8)
            {
                started = UsbFlashWriteFile64(fileName, startAddr, callback);
            }
            else
            {
                started = UsbFlashWriteFile86(fileName, startAddr, callback);
            }
            // 如果 UsbFlashWriteFile64 调用失败（例如，因为 DLL 加载失败），则直接设置 Task 为失败  
            if (!started)
            {
                tcs.SetException(new InvalidOperationException("调用 USBDLL 失败"));
            }

            // 等待回调设置结果  
            return await tcs.Task;
        }
        
    }
}
